package simpledb.tx.recovery;

import simpledb.server.SimpleDB;
import simpledb.buffer.*;
import simpledb.file.Block;
import simpledb.log.BasicLogRecord;

class SetIntRecord implements LogRecord {
  private int txnum, offset, val;
  private Block blk;

  /**
   * Creates a new setint log record.<br>
   * 创建一个新的setint日志记录
   * 
   * @param txnum the ID of the specified transaction 指定事务的ID
   * @param blk the block containing the value 包含该值的块
   * @param offset the offset of the value in the block 值在块中的偏移量
   * @param val the new value 新值
   */
  public SetIntRecord(int txnum, Block blk, int offset, int val) {
    this.txnum = txnum;
    this.blk = blk;
    this.offset = offset;
    this.val = val;
  }

  /**
   * Creates a log record by reading five other values from the log.<br>
   * 通过从日志中读取五个其他值来创建日志记录。参照{@link #writeToLog() writeToLog}方法中的实现
   * 
   * @param rec the basic log record
   */
  public SetIntRecord(BasicLogRecord rec) {
    txnum = rec.nextInt();
    String filename = rec.nextString();
    int blknum = rec.nextInt();
    blk = new Block(filename, blknum);
    offset = rec.nextInt();
    val = rec.nextInt();
  }

  /**
   * Writes a setInt record to the log. This log record contains the SETINT
   * operator, followed by the transaction id, the filename, number, and offset
   * of the modified block, and the previous integer value at that offset. <br>
   * 将setInt记录写入到日志，这个日志文件包含SETINT操作，后跟事务id，文件名，块编号，和修改块的偏移量，和在该偏移量之前的上一个整数值.
   * 
   * @return the LSN of the last log value 最后一个日志值的LSN
   */
  public int writeToLog() {
    Object[] rec = new Object[] { SETINT, txnum, blk.fileName(), blk.number(), offset, val };
    return logMgr.append(rec);
  }

  public int op() {
    return SETINT;
  }

  public int txNumber() {
    return txnum;
  }

  public String toString() {
    return "<SETINT " + txnum + " " + blk + " " + offset + " " + val + ">";
  }

  /**
   * Replaces the specified data value with the value saved in the log record.
   * The method pins a buffer to the specified block, calls setInt to restore
   * the saved value (using a dummy LSN), and unpins the buffer.<br>
   * 用保存在日志记录中的值替换指定位置的数据值。 该方法将缓冲区固定到指定的块，调用setInt来恢复保存的值（使用虚拟LSN），并取消固定缓冲区。
   * 
   * @see simpledb.tx.recovery.LogRecord#undo(int)
   */
  public void undo(int txnum) {
    BufferMgr buffMgr = SimpleDB.bufferMgr();
    Buffer buff = buffMgr.pin(blk);
    buff.setInt(offset, val, txnum, -1);
    buffMgr.unpin(buff);
  }
}
